/*
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

#pragma once

#include <unordered_map>

#include <mariana-trench/IncludeMacros.h>
#include <mariana-trench/Taint.h>

namespace marianatrench {

/**
 * FulFilledExploitabilityState tracks the source-as-transform sinks for
 * SourceSinkWithExploitabilityRule that need to be passed to the backwards
 * analysis for propagation. Exploitability rule has two stages of matching
 * taint flows and hence can be fulfilled or partially fulfilled.
 *
 * # Components of an exploitability rule:
 * - source: Regular taint source of the rule.
 * - sink: Regular taint sink of the rule.
 * - root-callable: the method where "source" flows into "sink"
 * - exploitability source: the effect source of the rule. This is usually added
 * on the call-effect exploitability port to methods that are marked as
 * "exported" in android manifest files. As with all call-effect sources, this
 is not propagated.
 * - source-as-transform sink: special sink which treats the "source" kind as a
 * transform on the "sink" kind. This is _materialized_ in forward analysis
 * when "source" flows into "sink". If neccessary, this sink is inferred on the
 * root-callable's call-effect exploitability port and propagated to callers in
 * backwards analysis.
 *
 * The rule is said to be partially fulfilled if we find the "source" to "sink"
 * flow and can form the "source-as-transform sink".
 *
 * The rule is said to be fulfilled when "exploitability source" flows to the
 * "source-as-transform sink" and an issue is created. Once the rule is
 fulfilled,
 * source-as-transform sinks do not need to be propagated further up the
 * call-chain. This stopping criteria for propagtion of the call-effect sink is
 * what differentiates it from the regular call-chain. This allows us to:
 * - find the shortest call-chain satisfying the exploitability rule.
 * - define "exploitability source" at multiple levels of the call-chain and
 * avoid duplicate issues.
 *
 * Partially fulfilled rule can be fulfilled in two cases:
 * - Trivially fulfilled when the root-callable also has the "exploitability
 source" we can trivially fulfill the rule and create an issue. In this case,
 the source-as-transform sink need not be materialized on the root-callable.
 * - Fulfilled when caller's "exploitability source" matches the callees
 * "source-as-transform sink" from the rule. In this case, callee's
 * source-as-transform sink need not be propagated to the caller.
 *
 * FulfilledExploitabilityState stores the information that needs to be passed
 * from forward to backward analysis to facilate the following:
 * - Backwards analysis to materialize new source-as-transform sinks identified
 * in forward analysis at root-callables.
 * - Implement the stopping criteria for the propagation source-as-transform
 * sinks iff an issue is found in forward analysis.
 */
class PartiallyFulfilledExploitabilityRuleState final {
 public:
  PartiallyFulfilledExploitabilityRuleState() = default;

  INCLUDE_DEFAULT_COPY_CONSTRUCTORS_AND_ASSIGNMENTS(
      PartiallyFulfilledExploitabilityRuleState)

  /**
   * Store the source-as-transform sink found while analyzing instruction to
   * pass to backwards analysis for propagation.
   */
  void add_source_as_transform_sinks(
      const IRInstruction* instruction,
      const Taint& source_as_transform_sinks);

  Taint source_as_transform_sinks(const IRInstruction* instruction) const;

 private:
  std::unordered_map<const IRInstruction*, Taint>
      instruction_to_source_as_transform_sinks_;
};

} // namespace marianatrench
